/*

MiscTapper
Version 1.2
Copyright (c) 1995 by Sean Luke
Donated to the MiscKit

Permission to use, copy, modify, and distribute this material 
for any purpose and without fee, under the restrictions as noted 
in the MiscKit copyright notice, is hereby granted, provided that
the MiscKit copyright notice and this permission notice 
appear in all source copies, and that the author's name shall not
be used in advertising or publicity pertaining to this 
material without the specific, prior written permission 
of the author.  SEAN O. LUKE  MAKES NO REPRESENTATIONS ABOUT THE
ACCURACY OR SUITABILITY OF THIS MATERIAL FOR ANY PURPOSE.  
IT IS PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.

*/

#import "MiscTapper.h"
#import <soundkit/soundkit.h>
#import <stdio.h>
#import <objc/objc-runtime.h>



#define			TAPPER_BUFFER_SIZE		65536
	// buffer size to deliver to stream reading in from microphone,
	// 64K of sound, or enough for about 8 seconds of CODEC.
#define 		TAPPER_TAG 				679201341		
	// if this object pauses, try changing this arbitrary tag
#define			TAPPER_REFRESH			.1
	// fraction of a second tapper checks for finished data.


// timed entry header

DPSTimedEntryProc tapper_timer
	(DPSTimedEntry teNum,double now, void* the_tapper);

@implementation MiscTapper
	
- _update					// Private
	{
	if (tapper_load) 
		{
		tapper_load=0;
		[tapper_stream recordSize:TAPPER_BUFFER_SIZE tag:TAPPER_TAG];
		}
	return self;	
	}	
	
- init
	{
	id returnval;
	returnval=[super init];
	tapper_device=[[NXSoundIn alloc] init];
	tapper_stream=[[NXRecordStream alloc] initOnDevice:tapper_device];
	[tapper_stream setDelegate:self];
	return returnval;
	}

- awake
	{
	id returnval;
	returnval=[super awake];
	tapper_device=[[NXSoundIn alloc] init];
	tapper_stream=[[NXRecordStream alloc] initOnDevice:tapper_device];
	[tapper_stream setDelegate:self];
	return returnval;
	}

- stop:sender
	{
	running=0;
	if (teNum) DPSRemoveTimedEntry(teNum);
	teNum=0;
	[tapper_stream deactivate];
	return self;
	}
	
	
- run:sender
	{
	if (running) return self;			// Already running.  Why re-run?
	tapper_load=1;						// This ensures that the tapper is
										// ready to accept stream info.
										// When deactivated a stream may not
										// have finished recording, so
										// tapper_load could possibly be 0!
	running=1;
	[tapper_stream activate];
	if (teNum) DPSRemoveTimedEntry(teNum);
	teNum=DPSAddTimedEntry(TAPPER_REFRESH, 
		(DPSTimedEntryProc) tapper_timer,
		(void*) self, (int) NX_RUNMODALTHRESHOLD);
	return self;
	}


- free
	{
	running=0;						// just in case
	[tapper_stream deactivate];
	if (teNum) DPSRemoveTimedEntry(teNum);
	teNum=0;
	[tapper_stream free];
	[tapper_device free];
	return [super free];
	}

- soundStream:sender didRecordData:(void*) data 
	size:(unsigned int) numBytes forBuffer:(int)tag
	{
	vm_deallocate(task_self(),(vm_address_t) data,(vm_size_t) numBytes);
	tapper_load=1;
	return self;
	}
	
	
@end


// timed entry procedure for periodically updating

DPSTimedEntryProc tapper_timer
	(DPSTimedEntry teNum,double now, void* the_tapper)
	{
	MiscTapper* temp_tapper=(MiscTapper*) the_tapper;
	[temp_tapper _update];
	return (void*) NULL;
	}


